﻿//////////////////////////////////////////////////////////////////////
// <copyright file=Triangle.cs">
//     Copyright (c) 2010
//     Released under  GNU GENERAL PUBLIC LICENSE
//     http://dev.perl.org/licenses/gpl1.html
// </copyright>
// <date> 3/27/2010 3:28:57 PM </date>
// <author> B. Endrovski </author>
// <web> http://furiouspixels.blogspot.com/ </web>
//////////////////////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ContourReconstruction
{
	public class Triangle : IComparable<Triangle>
	{
		// Vertices
		public Vector2D[] Vertices { get; private set; }
		
		// Neighbors
		public Triangle[] Neighbors { get; private set; }

		//  Circumscribed circle
		public Vector2D Circumcenter { get; private set; }
		public float Circumradius { get; private set; }

		/// <summary>
		/// Used as a metric for ordering the triangles, as is's taken from
		/// context and there are multiple ways of calculating such value
		/// it is calculated externaly and assigned
		/// </summary>
		public float M
		{ get; set; }

		/// <summary>
		/// Average of verts
		/// </summary>
		public Vector2D Center
		{
			get { return (Vertices[0] + Vertices[1] + Vertices[2]) / 3.0f; }
		}

		/// <summary>
		/// Get neighbor count
		/// </summary>
		public int NeighborCount
		{
			get
			{
				int c = 0;
				foreach (Triangle t in Neighbors)
					if (t != null) c++;
				return c;
			}
		}

		/// <summary>
		/// Triangle from vertices
		/// </summary>		
		public Triangle(Vector2D A, Vector2D B, Vector2D C)
		{
			this.Vertices = new Vector2D[3];
			this.Neighbors = new Triangle[3];
			//
			this.Vertices[0] = A;
			this.Vertices[1] = B;
			this.Vertices[2] = C;

			// Calculate circumscribed circle center
			// Tanslate origin to A
			// A'=0
			B = B - A;	// B'=B-A
			C = C - A;	// C'=C-A
			float D = 2 * (B.X * C.Y - B.Y * C.X);
			//
			if (Math.Abs(D) <= 0.000001)					// Vertices are colinear
			{
				// Any point should lay inside the circle
				Circumcenter = new Vector2D(0, 0);
				Circumradius = Single.MaxValue;
			}
			else
			{
				// Normal triangle
				float x = (C.Y * B.LengthSq - B.Y * C.LengthSq) / D;
				float y = (B.X * C.LengthSq - C.X * B.LengthSq) / D;
				Circumcenter = new Vector2D(x, y) + A;	// Transalte back
				Circumradius = A.Distance(Circumcenter);
			}

			M = 0.0f;
		}		

		/// <summary>
		/// Defalut comparator
		/// </summary>
		public int CompareTo(Triangle other)
		{
			return this.M.CompareTo(other.M);
		}
	}

}
